using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Web.UI;
using Sedna.Core.Security;
using log4net;

namespace Sedna.Core.Controller.Configurations
{
    public class FinenessStringParser : IDataTranslator
    {
        private ILog log = LogManager.GetLogger(typeof(FinenessStringParser));

        private IPrincipalWrapper principalWrapper;
        private object defaultValue = 0;
        private bool floorToOne = true;
        private bool ceilToZero = true;
        private object valueOnNotNumber = null;

        # region Properties

        /// <summary>
        /// Apply this value if incoming value is null or empty
        /// </summary>
        public object DefaultValue
        {
            set { defaultValue = value; }
        }

        /// <summary>
        /// Apply value '1' if incoming value is greater than '1'
        /// </summary>
        public bool FloorToOne
        {
            set { floorToOne = value; }
        }

        /// <summary>
        /// Apply value '0' if incoming value is lower than '0'
        /// </summary>
        public bool CeilToZero
        {
            set { ceilToZero = value; }
        }

        /// <summary>
        /// Apply this value if it's not null and incoming value isn't a number.
        /// Rules 'FloorToOne' and 'CeilToZero' are applied for this value.
        /// </summary>
        public object ValueOnNotNumber
        {
            set { valueOnNotNumber = value; }
        }

        public IPrincipalWrapper PrincipalWrapper
        {
            set { principalWrapper = value; }
        }        

        # endregion

        public object Translate(Control control, object value)
        {
            return Translate(control, value, null);            
        }

        public object Translate(Control control, object value, Type targetType)
        {
            if (targetType == null)
            {
                string errorMessage = "TargetType is null";
                log.Error(errorMessage);
                throw new ControllerConfigurationException(errorMessage);
            }
            
            bool WasValueNotNumber = false;

            if (value == null)
                value = defaultValue;
            else
            {
                string strValue = value as string;

                if (strValue != null)
                {
                    strValue = strValue.Trim();
                    
                    if (strValue.Length == 0)
                        value = defaultValue;
                    else
                    {
                        bool HadMinus = false;

                        if (strValue[0] == '-' && strValue.Length > 1)
                        {
                            HadMinus = true;
                            strValue = strValue.Substring(1);
                        }
                        
                        Regex r = new Regex("^([0-9.,]*)");
                        Match m = r.Match(strValue);

                        if (m.Groups[1].Value.Length != strValue.Length)
                        {
                            WasValueNotNumber = true;
                            
                            if (valueOnNotNumber != null)
                            {
                                value = valueOnNotNumber;
                            }
                        }
                        else
                            value = (HadMinus) ? "-" + m.Groups[1].Value : m.Groups[1].Value;
                    }
                }
                else
                {
                    string errorMessage = string.Format("Not supporting value type: {0}", value.GetType());
                    log.Error(errorMessage);
                    throw new ControllerConfigurationException(errorMessage);
                }
            }
            
            
            if (targetType == typeof(double))
            {
                try
                {
                    double fineness = Convert.ToDouble(defaultValue);
                    try
                    {
                        fineness = Convert.ToDouble(value, principalWrapper.Culture);
                    }
                    catch{}

                    //double fineness = Convert.ToDouble(value, principalWrapper.Culture);

                    if (fineness > 1 && floorToOne && !WasValueNotNumber)
                        fineness = 1;

                    if (fineness < 0 && ceilToZero && !WasValueNotNumber)
                        fineness = 0;
                    
                    return fineness;
                }
                catch (Exception e)
                {
                    log.Error(e.Message);
                    throw new ControllerConfigurationException(e.Message);
                }
            }
            else
            {
                string errorMessage = string.Format("Not supporting fineness target type: {0}", targetType);
                log.Error(errorMessage);
                throw new ControllerConfigurationException(errorMessage);
            }                                   
        }
    }
}
